К сожалению, существует множество правил, которые ограничивают использование управляемых типов (классов, структур, интерфейсов), что ведет к затруднениям в работе с ними по сравнению с традиционными неуправляемыми типами в C++. Эти правила также оказывают некоторое влияние на то, как управляемый и неуправляемый коды могут взаимодействовать друг с другом.
1. Управляемый тип не может быть наследован из неуправляемого типа. С другой стороны, неуправляемый тип не может быть наследован из управляемого типа. Это значит, что структуры иерархий наследственности управляемых и неуправляемых классов всегда отделены друг от друга.
2. Управляемые типы не могут иметь друзей (т.е. дружественных функций, классов,
структур и интерфейсов). Естественно, данное правило не распространяется на
неуправляемые классы C++. Это, конечно, может быть и не так важно для многих
программистов, ведь многие рассматривают дружественность как нарушение важной
концепции объектно-ориентированного программирования, называемой инкапсуляцией.
Неуправляемые типы могут иметь друзей, как и классы в традиционном C++; однако
неуправляемые типы могут иметь друзей только из числа неуправляемых типов.
//ManagedAndUnmanagedTypes.срр
fusing <mscorlib.dll>
using namespace System;
// использование пространства имен Система;
#pragma warning(disable : 4101)
// *pragma предупреждение (отключите: 4101)
// игнорировать отсутствие ссылок на локальные переменные (unref
local)
_gc class MemberManagedClass {};
// используется как элемент данных
// класс сборщика мусора MemberManagedClass {};
_nogc class MemberUnmanagedClass {};
// класс MemberUnmanagedClass используется как элемент данных
_gc class FriendManagedClass {};
// класс сборщика мусора FriendManagedClass используется как
друг
_nogc class FriendUnmanagedClass {};
// класс FriendUnmanagedClass используется как друг
_gc class ManagedClass
// класс сборщика мусора ManagedClass
{
public:
MemberUnmanagedClass urn; //OK: внедренный неуправляемый MemberUnmanagedClass
*pum; //OK: указатель на неуправляемый MemberUnmanagedClass &rum; //OK:
ссылка на неуправляемый
//MemberManagedClass m; // Ошибка: не любит стека
MemberManagedClass *pm; //OK: указатель на управляемый
MemberManagedClass &rm; //OK: ссылка на управляемый
ManagedClass() : // необходим для инициализации ссылки
rm(*new MemberManagedClass), // требуется компилятором! rum(*new
MemberUnmanagedClass), // требуется компилятором! pm(new MemberManagedClass)
// не требуется компилятором
{}
// Ошибки: не может иметь никаких друзей // в управляемом классе
//friend FriendManagedClass; // друг //friend FriendUnmanagedClass; // друг
};
_nogc class UnmanagedClass
// класс UnmanagedClass
{
public:
MemberUnmanagedClass um; //OK: внедренный неуправляемый MemberUnmanagedClass
*pum; //OK: указатель на неуправляемый MemberUnmanagedClass Srum; //OK: ссылка
на неуправляемый
//MemberManagedClass m; // Ошибка: не любит стека
//MemberManagedClass *pm;
// Ошибка: управляемый* в неуправляемом
MemberManagedClass &rm; //OK: ссылка на управляемый (???)
UnmanagedClass() : // необходим для инициализации ссылки
rm(*new MemberManagedClass), // требуется компилятором! rum(*new
MemberUnmanagedClass) // требуется компилятором!
{}
// Ошибка: нельзя объявить управляемый друг // в неуправляемом
//friend FriendManagedClass; // друг friend FriendUnmanagedClass;
// друг - OK
};
_gc class SuperManagedClass {};
// класс сборщика мусора SuperManagedClass
_nogc class SuperUnmanagedClass {}; // класс SuperUnmanagedClass
// ошибка: управляемый тип не может происходить
//от неуправляемого типа
//_gc class BadSubManagedClass : SuperUnmanagedClass {};
// класс сборщика мусора
// BadSubManagedClass: SuperUnmanagedClass
// ошибка: неуправляемый тип не может происходить
//от управляемого типа
//_nogc class BadSubUnmanagedClass : SuperManagedClass {};
// класс BadSubUnmanagedClass: SuperManagedClass {};
//OK: can derive from machine managed/unmanaged super class
// OK: может происходить от суперкласса,
// управляемого/неуправляемого машиной
_gc class OKSubManagedClass : public SuperManagedClass {};
// класс сборщика мусора
// OKSubManagedClass: SuperManagedClass
_nogc class OKSubUnmanagedClass : SuperUnmanagedClass {};
// класс OKSubUnmanagedClass: SuperUnmanagedClass
void main(void) {
UnmanagedClass *pumc = new UnmanagedClass;
// старый C++
UnmanagedClass umc; // старый C++
UnmanagedClass srumc = *new UnmanagedClass;
// старый C++
ManagedClass *pmc = new ManagedClass;
//OK: управляемая динамически распределяемая
// область памяти
//ManagedClass me; // Ошибка: боится стека
ManagedClass &rmc = *new ManagedClass;
// OK: управляемая динамически распределяемая // область памяти
}